package com.zhixi.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.zhixi.common.MyMetaObjectHandler;
import com.zhixi.common.R;
import com.zhixi.common.SharedVariablesCurrent;
import com.zhixi.dto.DishDto;
import com.zhixi.pojo.Category;
import com.zhixi.pojo.Dish;
import com.zhixi.pojo.DishFlavor;
import com.zhixi.service.CategoryService;
import com.zhixi.service.DishFlavorService;
import com.zhixi.service.DishService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @ClassName DishController
 * @Author zhangzhixi
 * @Description 菜品管理
 * @Date 2022-7-11 12:50
 * @Version 1.0
 */
@RestController
@RequestMapping("/dish")
@Slf4j
@Api(value = "菜品管理", tags = "菜品管理")
public class DishController {
    @Autowired
    private DishService dishService;

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 新增菜品
     *
     * @param dishDto 菜品数据传输对象
     * @return R结果对象
     */
    @PostMapping
    @ApiOperationSupport(author = "zhangzhixi")
    @ApiOperation(value = "新增菜品", notes = "新增菜品")
    public R<String> save(@RequestBody DishDto dishDto, HttpServletRequest request) {
        // 保存菜品的同时，保存菜品的口味
        dishService.saveDishFlavor(dishDto, request);
        return R.success("菜品保存成功");
    }

    /**
     * 查询菜品管理页面的菜品列表
     *
     * @param page     分页对象
     * @param pageSize 每页显示的条数
     * @return R结果对象
     */
    @GetMapping("/page")
    @ApiOperation(value = "查询菜品管理页面的菜品列表", notes = "查询菜品管理页面的菜品列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "页码", required = true, paramType = "query", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "pageSize", value = "每页显示的条数", required = true, paramType = "query", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "name", value = "菜品名称", required = false, paramType = "query", dataTypeClass = String.class),
    })
    public R<Page> page(int page, int pageSize, @RequestParam(required = false) String name) {
        log.info("page = {}, pageSize = {} ,name={}", page, pageSize, name);
        Page<Dish> dishPage = dishService.page(page, pageSize, name);
        return R.success(dishPage);
    }


    /**
     * 根据菜品id查询菜品
     *
     * @param id 菜品id
     * @return R结果对象
     */
    @ApiOperation(value = "根据菜品id查询菜品", notes = "根据菜品id查询菜品")
    @GetMapping("/{id}")
    public R<DishDto> getDish(@PathVariable Long id) {
        DishDto dishDto = dishService.getDishWithFlavor(id);
        return R.success(dishDto);
    }

    /**
     * 更新菜品
     *
     * @param dishDto 菜品数据传输对象
     * @param request 请求对象
     * @return R结果对象
     */
    @PutMapping
    @ApiOperation(value = "更新菜品", notes = "更新菜品")
    public R<String> updateDish(@RequestBody DishDto dishDto, HttpServletRequest request) {
        // 更新菜品的同时，更新菜品的口味
        dishService.updateWithFlavor(dishDto, request);
        return R.success("菜品修改成功");
    }

    /**
     * 删除菜品，可以批量删除
     *
     * @param id 菜品id
     * @return R结果对象
     */
    @DeleteMapping
    @ApiOperation(value = "删除菜品", notes = "删除菜品")
    public R<String> deleteDish(@RequestParam("ids") Long[] id) {
        dishService.deleteBatch(Arrays.asList(id));
        return R.success("菜品删除成功");
    }

    /**
     * 更改菜品的状态-启用/禁用(支持批量)
     *
     * @param status  菜品状态
     * @param id      菜品id
     * @param request 请求对象
     * @return R结果对象
     */
    @PostMapping("/status/{status}")
    @ApiOperation(value = "更改菜品的状态-启用/禁用(支持批量)", notes = "更改菜品的状态-启用/禁用(支持批量)")
    public R<String> updateDishStatus(@PathVariable("status") int status, @RequestParam("ids") Long[] id, HttpServletRequest request) {
        // 修改菜品状态为下架
        dishService.updateStatus(id, status, request);
        return R.success("菜品状态修改成功");
    }

    /**
     * 查询菜品的列表
     *
     * @param dish 菜品对象
     * @return R结果对象
     */
    @GetMapping("/list")
    @ApiOperation(value = "查询菜品的列表", notes = "查询菜品的列表")
    public R<List<Dish>> listDish(Dish dish) {
        List<Dish> dishList = null;
        // 构造redis的key
        String key = "dish_" + dish.getCategoryId() + "_" + dish.getStatus();

        // 缓存中有，直接返回缓存中的数据
        dishList = (List<Dish>) redisTemplate.opsForValue().get(key);
        if (dishList != null) {
            return R.success(dishList);
        }

        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        // 1、构造查询条件
        queryWrapper.eq(Dish::getStatus, 1)
                .eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId())
                .orderByAsc(Dish::getSort)
                .orderByDesc(Dish::getUpdateTime);

        // 3、查询菜品列表
        dishList = dishService.list(queryWrapper);

        // 4、设置菜品的口味数据
        dishList = dishList.stream().peek(item -> {
            // 查询菜品的口味
            List<DishFlavor> dishFlavorList = dishFlavorService.list(new LambdaQueryWrapper<DishFlavor>().eq(DishFlavor::getDishId, item.getId()));
            item.setFlavors(dishFlavorList);
        }).collect(Collectors.toList());

        // 5、Redis中没有数据，在查询完DB后，将查询后的数据添加到redis中去
        redisTemplate.opsForValue().set(key, dishList, 60, TimeUnit.MINUTES);
        return R.success(dishList);
    }
}
